#pragma once
#include<iostream>
using namespace std;
#include<unistd.h>
#include<string>
#include<queue>
#include<pthread.h>
#include"Task.hpp"

//基于阻塞队列的生产消费者模型
//1：2个条件变量，一把锁，一个队列，
template<class T>
class block_queue{
public:
    //默认缺省设置为5，这样直接构造出来就有5个空间
    block_queue(const int& maxcap = 5):_maxcap(maxcap){
        //构造锁和条件变量
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        pthread_cond_init(&_pond,nullptr);

    }

    void push(const T& in){//输入数据采用引用
        //上锁
        pthread_mutex_lock(&_mutex);
        //判断
        //满了就不能插入，而是去排队
        while(full()){
            pthread_cond_wait(&_pond,&_mutex);
        }

        //到这里说明队列没有满
        _queue.push(in);
        //到这里说明队列里面至少有一个数据

        
        pthread_cond_signal(&_cond);//这里唤醒的是消费者线程

        //解锁
        pthread_mutex_unlock(&_mutex);

    }

    void pop(T* out){//输出型参数采用*
        //加锁
        pthread_mutex_lock(&_mutex);
        while(empty()){
            pthread_cond_wait(&_cond,&_mutex);
        }
        *out = _queue.front();
        _queue.pop();

        
        pthread_cond_signal(&_pond);//这里唤醒的是生产者线程

        pthread_mutex_unlock(&_mutex);

    }

    ~block_queue(){
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        pthread_cond_destroy(&_pond);
    }


private:
    bool full(){
        return _queue.size() == _maxcap;
    }
    bool empty(){
        return _queue.empty();
    }



public:
    queue<T> _queue;
    int _maxcap;//队列的最大容量
    pthread_mutex_t _mutex;//互斥锁
    pthread_cond_t _cond;//消费者的条件变量
    pthread_cond_t _pond;//生产者的条件变量
};



